/******************************************************************************
 * @file     iic.c
 * @brief    Bootloader中软件iic相关函数
 * @author   Ruilist
 * @date     2025-08-21
 * @version  V1.0.0
 * @copyright Copyright (c) 2025
 *
 * @note     1 tab = 4 space
 *
 * @par 日志:
 * - V1.0.0 2025-08-21 Ruilist
 *****************************************************************************/

//******************************** Includes *********************************//

#include "iic.h"

//******************************** Includes *********************************//

//******************************** Declaring ********************************//

/**
 * @brief   软iic的io接口初始化，SDA PB9，SCL PB8
 *
 * @param   void
 *
 * @return  void
 *
 */
void i2c_gpio_init( void )
{
    GPIO_InitTypeDef GPIO_InitStruct = { 0 };

    RCC_AHB1PeriphClockCmd( EEPROM_I2C_GPIO_CLK, ENABLE );

    GPIO_InitStruct.GPIO_Pin   = EEPROM_I2C_SCL_PIN | EEPROM_I2C_SDA_PIN;
    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_OUT;
    GPIO_InitStruct.GPIO_PuPd  = GPIO_PuPd_NOPULL;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
    GPIO_Init( EEPROM_I2C_GPIO_PORT, &GPIO_InitStruct );

    i2c_Stop();
}

/**
 * @brief   软iic的delay函数
 *
 * @param   void
 *
 * @return  void
 *
 */
void i2c_Delay( void )
{
    uint8_t i;
    for ( i = 0; i < 40; i++ )
    {
    };
}

/**
 * @brief   软iic的start函数
 *
 * @param   void
 *
 * @return  void
 *
 */
void i2c_Start( void )
{
    EEPROM_I2C_SCL_1();
    EEPROM_I2C_SDA_1();
    i2c_Delay();
    EEPROM_I2C_SDA_0();
    i2c_Delay();
    EEPROM_I2C_SCL_0();
    i2c_Delay();
}

/**
 * @brief   软iic的stop函数
 *
 * @param   void
 *
 * @return  void
 *
 */
void i2c_Stop( void )
{
    EEPROM_I2C_SDA_0();
    EEPROM_I2C_SCL_1();
    i2c_Delay();
    EEPROM_I2C_SDA_1();
    i2c_Delay();
}

/**
 * @brief   软iic的ack函数
 *
 * @param   void
 *
 * @return  void
 *
 */
void i2c_Ack( void )
{
    EEPROM_I2C_SDA_0();
    i2c_Delay();
    EEPROM_I2C_SCL_1();
    i2c_Delay();

    EEPROM_I2C_SCL_0();
    i2c_Delay();

    EEPROM_I2C_SDA_1(); /* CPU释放SDA总线 */
    i2c_Delay();
}

/**
 * @brief   软iic的nack函数
 *
 * @param   void
 *
 * @return  void
 *
 */
void i2c_NAck( void )
{
    EEPROM_I2C_SDA_1();
    i2c_Delay();
    EEPROM_I2C_SCL_1();
    i2c_Delay();
    EEPROM_I2C_SCL_0();
    i2c_Delay();
}

/**
 * @brief   等待iic设备应答
 *
 * @param   void
 *
 * @return  uint8_t
 * @retval  0 正确应答
 * @retval  1 无器件响应
 *
 */
uint8_t i2c_WaitAck( void )
{
    uint8_t ret;
    EEPROM_I2C_SDA_1();
    i2c_Delay();

    EEPROM_I2C_SCL_1();
    i2c_Delay();

    if ( EEPROM_I2C_SDA_READ() )
    {
        ret = 1;
    }
    else
    {
        ret = 0;
    }
    EEPROM_I2C_SCL_0();
    i2c_Delay();

    return ret;
}

/**
 * @brief   软iic发送一个字节
 *
 * @param   uint8_t Byte 要发送的字节
 *
 * @return  void
 *
 */
void i2c_SendByte( uint8_t Byte )
{
    uint8_t i;
    for ( i = 0; i < 8; i++ )
    {
        if ( Byte & 0x80 )
        {
            EEPROM_I2C_SDA_1();
        }
        else
        {
            EEPROM_I2C_SDA_0();
        }
        i2c_Delay();

        EEPROM_I2C_SCL_1();
        i2c_Delay();
        EEPROM_I2C_SCL_0();
        i2c_Delay();

        if ( i == 7 )
        {
            EEPROM_I2C_SDA_1();
        }
        Byte <<= 1;
        i2c_Delay();
    }
}

/**
 * @brief   软iic接收一个字节
 *
 * @param   void
 *
 * @return  uint8_t
 * @retval  byte 接收到的字节
 *
 */
uint8_t i2c_ReadByte( void )
{
    uint8_t i;
    uint8_t value;

    value = 0;
    for ( i = 0; i < 8; i++ )
    {
        value <<= 1;
        EEPROM_I2C_SCL_1();
        i2c_Delay();
        if ( EEPROM_I2C_SDA_READ() )
        {
            value++;
        }
        EEPROM_I2C_SCL_0();
        i2c_Delay();
    }
    return value;
}

/**
 * @brief   软iic接收一个字节
 *
 * @param   uint8_t Address
 *
 * @return  uint8_t
 * @retval  0 正确应答
 * @retval  1 无器件响应
 *
 */
uint8_t i2c_CheckDevice( uint8_t Address )
{
    uint8_t ack;
    i2c_gpio_init();
    i2c_Start();
    i2c_SendByte( Address | EEPROM_I2C_WR );
    ack = i2c_WaitAck();
    i2c_Stop();
    return ack;
}

//******************************** Declaring ********************************//
